package com.classroommanagesystem.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.classroommanagesystem.domain.dto.LoginDTO;
import com.classroommanagesystem.domain.dto.RegisterDTO;
import com.classroommanagesystem.domain.dto.UpdatePasswordDTO;
import com.classroommanagesystem.domain.dto.UpdateUserDTO;
import com.classroommanagesystem.domain.entity.User;
import com.classroommanagesystem.exception.BusinessException;
import com.classroommanagesystem.mapper.UserMapper;
import com.classroommanagesystem.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.classroommanagesystem.utils.JwtUtil;
import com.classroommanagesystem.utils.PasswordUtils;
import com.classroommanagesystem.utils.ThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author author
 * @since 2025-10-24
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private PasswordEncoder passwordEncoder;

    /**
     * 根据id获取用户信息
     * @param id
     * @return
     */
    @Override
    @Cacheable(cacheNames = "user", key = "#id")
    public User getById(Serializable id) {
        return super.getById(id);
    }

    /**
     * 登录
     *
     * @param dto
     * @return
     */
    @Override
    public String login(LoginDTO dto) {
        // 查询用户是否存在
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<User>()
                .eq(User::getUsername, dto.getUsername())
                .eq(User::getStatus, 1);
        User user = userMapper.selectOne(queryWrapper);
        if (user == null) {
            log.info("登录失败");
            throw new BusinessException("用户不存在或已被禁用");

        }
        // 判断密码是否正确
        if (PasswordUtils.isPassword(user.getPassword(), dto.getPassword())) {
            // 生成token
            Map<String, Object> claims = new HashMap<>();
            claims.put("id", user.getId());
            claims.put("username", user.getUsername());
            String token = JwtUtil.genToken(claims);
            // 将用户id存入ThreadLocal
            ThreadLocalUtil.setCurrentId(user.getId());

            // 将token存入redis
            stringRedisTemplate.opsForValue().set("token:" + user.getId(), token, 24, TimeUnit.HOURS);

            return token;
        } else {
            log.info("登录失败");
            throw new BusinessException("密码错误");
        }
    }

    /**
     * 注册
     *
     * @param dto
     */
    @Override
    public void register(RegisterDTO dto) {
        // 查询用户是否存在
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<User>()
                .eq(User::getUsername, dto.getUsername())
                .eq(User::getStatus, 1);
        User user = userMapper.selectOne(queryWrapper);
        if (user != null) {
            throw new BusinessException("用户已存在");
        }
        // 加密密码
        String encode = passwordEncoder.encode(dto.getPassword());
        User user1 = new User();
        user1.setUsername(dto.getUsername());
        user1.setPassword(encode);
        user1.setStatus(1);
        user1.setRealName(dto.getRealName());
        user1.setPhone(dto.getPhone());
        userMapper.insert(user1);
    }

    /**
     * 登出
     */
    @Override
    public void logout() {
        Long id = ThreadLocalUtil.getCurrentId();
        // 清除ThreadLocal
        ThreadLocalUtil.removeCurrentId();
        // 清除redis中的token
        stringRedisTemplate.delete("token:" + id);
    }

    /**
     * 修改密码
     *
     * @param dto
     */
    @Override
    public void updatePassword(UpdatePasswordDTO dto) {
        Long id = ThreadLocalUtil.getCurrentId();

        // 查询用户是否存在
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<User>()
                .eq(User::getId, id)
                .eq(User::getStatus, 1);
        User user = userMapper.selectOne(queryWrapper);
        if (user == null) throw new BusinessException("用户不存在");
        // 判断密码是否正确
        if (!passwordEncoder.matches(dto.getOldPassword(), user.getPassword()))
            throw new BusinessException("旧密码不正确");

        // 加密密码
        String encode = passwordEncoder.encode(dto.getNewPassword());
        user.setPassword(encode);
        userMapper.updateUser(user);
    }

    /**
     * 修改信息
     * @param dto
     */
    @Override
    @CacheEvict(value = "user", key = "#result.id")
    public void updateUserInfo(UpdateUserDTO dto) {
        Long currentId = ThreadLocalUtil.getCurrentId();
        User user = new User();
        BeanUtils.copyProperties(dto, user);
        user.setId(currentId);
        userMapper.updateUser(user);
    }
}
